package EstimatorPackage;

import ClassAlgebra.ComplexExpression;
import ClassAlgebra.ComplexProbExpr;
import ClassAlgebra.EmptyExpression;
import ClassAlgebra.Expression;

import ClassAlgebra.ProbExpr;
import ClassAlgebra.SimpleExpression;
import ClassAlgebra.SimpleProbExpr;
import ClassAlgebra.ZeroProbExpr;
import DataSetPackage.SimpleView;
import DataSetPackage.View;
import HierarchyPackage.AffixHierarchies.SuffixHClass;

/**
 *
 * @author Martin Haulrich
 */
public class SimSuffixEstimatorExp extends AbstractEstimatorExp implements EstimatorExp {

//    final static String STOP = "$";
//
//    final static String START = "^";

    final EmpSuffix est;


    public SimSuffixEstimatorExp(EmpSuffix est) {
        super();
        this.est = est;


    }


    public SimSuffixEstimatorExp(EmpSuffix est, int cacheSize) {
        super(cacheSize);
        this.est = est;


    }


    @Override
    public double getEstimate(Integer did, View v) {
    //    double estimate = est.getEstimate(START + ((SimpleView) v).getFeatures(did)[0] + STOP);
        double estimate = est.getEstimate(((SimpleView) v).getFeature(did));
      //  System.err.println("SufEstExp: " + did + " : " + START + ((SimpleView) v).getFeatures(did)[0] + STOP +  "  = " + estimate);
        return estimate;
    }


    @Override
    public double getEstimateRec(ProbExpr pe) {

        if (pe instanceof ZeroProbExpr) {
            return -20000000;
        }

        if (pe instanceof SimpleProbExpr) {
            //     System.err.println("SimpleProp");
            Expression ce = ((SimpleProbExpr) pe).e;
            return getClassEst(ce);
        }

        ComplexProbExpr cpe = (ComplexProbExpr) pe;
        if (cpe.operation == ComplexProbExpr.DIFFERENCE) {
            double se1 = getEstimateRec(cpe.pe1);
            double se2 = getEstimateRec(cpe.pe2);
            double l = Math.max(se1, se2);
            double res = l + Math.log10(Math.pow(10, se1 - l) - Math.pow(10, se2 - l));
            return res;
        }
        if (cpe.operation == ComplexProbExpr.SUM) {
            double se1 = getEstimateRec(cpe.pe1);
            double se2 = getEstimateRec(cpe.pe2);
            double l = Math.max(se1, se2);
            double res = l + Math.log10(Math.pow(10, se1 - l) + Math.pow(10, se2 - l));
            return res;

        }

        System.err.println("SuffixEstimatorExp.getEstimateRec\nThis should not happen!");

        return 0;
    }


    private double getClassEst(Expression e) {
        //      System.err.println("G: " + e);
        if (e instanceof SimpleExpression) {
            //         System.err.println("Returnig simple");
            return est.getEstimate(((SuffixHClass) ((SimpleExpression) e).c).affix); 
            //return est.getEstimate(((SuffixHClass) ((SimpleExpression) e).c).affix + STOP);
        }
        if (e instanceof EmptyExpression) {
            return -2000000000;
        }
        if (e instanceof ComplexExpression) {
            ComplexExpression ce = (ComplexExpression) e;
            if (ce.operation == ComplexExpression.INTERSECTION) {
                if ((ce.e1 instanceof SimpleExpression) && (ce.e2 instanceof SimpleExpression)) {
                    String suffix1 = ((SuffixHClass) ((SimpleExpression) ce.e1).c).affix;
                    String suffix2 = ((SuffixHClass) ((SimpleExpression) ce.e2).c).affix;
                    // Return the probabiblity of the longest suffix unless the two suffixes are disjunctive. In that case return 0;
                    if (suffix1.endsWith(suffix2)) {
              //          return est.getEstimate(suffix1 + STOP);
                        return est.getEstimate(suffix1);
                    }
                    if (suffix2.endsWith(suffix1)) {
                        //return est.getEstimate(suffix2 + STOP);
                        return est.getEstimate(suffix2);
                    }
                    return -20000000;
                }
            }
        }

        System.err.println("SuffixEstimatorExp.getClassEst");
        System.err.println("I THINK that this should not happen because all expression should be reduced until there are only");
        System.err.println("simpleexpression and intersection of simple expressions left");
        System.err.println("Here the expression is: " + e);

        return 0;
    }
}

